<template>
  <div>
    <el-dialog v-model="dialogVisible" class="c-dialog-fixed" width="700px" :title="dialogTitle" @closed="handleClosed"
      @close="handleClose">
      <el-form ref="formRef" label-width="auto" :model="formData" :rules="rules" v-loading="loading">
        <el-divider>角色信息</el-divider>
        <el-form-item label="角色名称" prop="name">
          <el-input v-model="formData.name" placeholder="填写角色名称"></el-input>
        </el-form-item>
        <el-form-item label="角色备注" prop="remarks">
          <el-input v-model="formData.remarks" placeholder="填写角色备注"></el-input>
        </el-form-item>
        <el-form-item label="菜单权限">
          <el-table ref="table" :data="menuPermissionTreeData" :select-on-indeterminate="false" border stripe
            default-expand-all row-key="id">
            <!-- <el-table-column type="selection" width="35" align="center"></el-table-column> -->
            <el-table-column width="35" type="index" align="center">
              <template #header>
                <el-checkbox :model-value="isAllChecked(menuPermissionTreeData)"
                  :indeterminate="isIndeterminate(menuPermissionTreeData)"
                  @change="checkedRecursion($event, menuPermissionTreeData)">
                </el-checkbox>
              </template>
              <template #default="{ row }">
                <el-checkbox v-if="row.children" :indeterminate="isIndeterminate(row.children)"
                  :model-value="isAllChecked(row.children)"
                  @change="checkedRecursion($event, row.children)"></el-checkbox>
                <el-checkbox v-else v-model="row.isChecked"></el-checkbox>
              </template>
            </el-table-column>
            <el-table-column prop="name" label="菜单名称" min-width="120"></el-table-column>
            <el-table-column width="250">
              <template #header>
                <el-checkbox :disabled="!hasChecked(menuPermissionTreeData)"
                  :indeterminate="isIndeterminate(menuPermissionTreeData, true)"
                  :model-value="isAllChecked(menuPermissionTreeData, true)"
                  @change="checkedRecursion($event, menuPermissionTreeData, true)">全选</el-checkbox>
              </template>
              <template #default="{ row }">
                <el-checkbox v-if="row.children" :model-value="isAllChecked(row.children, true)"
                  :disabled="!hasChecked(row.children)" :indeterminate="isIndeterminate(row.children, true)"
                  @change="checkedRecursion($event, row.children, true)">全选
                </el-checkbox>
                <template v-else>
                  <el-checkbox v-for="p in row.permissions" :disabled="!row.isChecked" :key="p.code"
                    v-model="p.isChecked">
                    {{ p.name }}
                  </el-checkbox>
                </template>
              </template>
            </el-table-column>
          </el-table>
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button type="primary" @click="save" :loading="loading">保存</el-button>
      </template>
    </el-dialog>
  </div>
</template>
<script setup>
import roleApi from "@/api/sys/role";
import menuApi from "@/api/sys/menu";
import { ref, useTemplateRef } from "vue";
import { toTreeData, cloneDeepObject, cloneObjectValue } from "@/utils/common"
import { ElMessage } from "element-plus";

const props = defineProps({

})
const dialogTitle = ref("")
const formData = ref({
  id: 0,
  name: "",
  remarks: "",
  menuPermissions: []
})
const saved = ref(false)
const loading = ref(false)
const dialogVisible = ref(false)
//菜单权限数据
const menuPermissionData = ref([])
//菜单权限树型数据
const menuPermissionTreeData = ref([])
const rules = ref({
  name: [
    { required: true, message: "请填写角色名称" },
    {
      validator: async (rule, value, callback) => {
        const res = await roleApi.checkExistByName(value, formData.value.id);
        if (res.data) {
          callback("角色名已存在");
        } else {
          callback();
        }
      }, trigger: "blur"
    }
  ]
})

const emits = defineEmits(["close-saved"])

const formRef = useTemplateRef("formRef")

const initMenuPermissionData = async () => {
  let res = await menuApi.getMenuPermissionList();
  res.data.forEach(item => {
    item.isChecked = false;
    item.permissions.forEach(i => i.isChecked = false)
  });
  menuPermissionData.value = res.data;
  menuPermissionTreeData.value = toTreeData(res.data);
}
const openCreate = async () => {
  dialogTitle.value = "创建角色";
  dialogVisible.value = true
  loading.value = true
  await initMenuPermissionData()
  loading.value = false
}
const openEditById = async (id) => {
  dialogTitle.value = "编辑角色";
  dialogVisible.value = true
  loading.value = true;
  await initMenuPermissionData()
  const res = await roleApi.getEditById(id)
  formData.value = res.data;
  setMenuPermissionData(res.data.menuPermissions);
  loading.value = false;
}
const handleClose = () => {
  if (saved.value) {
    emits("close-saved");
  }
}
//窗口关闭后
const handleClosed = () => {
  dialogTitle.value = "";
  saved.value = false;
  formRef.value.resetFields();
  menuPermissionData.value = []
  menuPermissionTreeData.value = []
}
//设置菜单权限值
const setMenuPermissionData = (data) => {
  data.forEach(item => {
    var d = menuPermissionData.value.find(i => i.id == item.menuId);
    if (d != null) {
      d.isChecked = true;
      d.permissions.forEach(i => i.isChecked = item.permissionCodes.includes(i.code))
    }
  })
}
const resetMenuPermissionData = () => {
  let _reset = function (data) {
    data.forEach(item => {
      item.isChecked = false;
      item.permissions.forEach(i => i.isChecked = false)
      if (item.children) {
        _reset(item.children);
      }
    });
  };
  _reset(menuPermissionData.value);
}
//菜单权限是否全部勾选
const isAllChecked = (children, isPermission = false) => {
  return children.length > 0 && children.every(item => {
    if (item.children) {
      return isAllChecked(item.children, isPermission);
    } else {
      if (isPermission) {
        return item.permissions.every(i => i.isChecked);
      } else {
        return item.isChecked;
      }
    }
  })
}

//菜单权限是否有一个勾选
const hasChecked = (children, isPermission = false) => {
  return children && children.some(item => {
    if (item.children) {
      return hasChecked(item.children, isPermission);
    } else {
      if (isPermission) {
        return item.permissions.some(i => i.isChecked);
      } else {
        return item.isChecked;
      }
    }
  })
}

const isIndeterminate = (children, isPermission = false) => {
  return hasChecked(children, isPermission) && !isAllChecked(children, isPermission)
}

//递归勾选
const checkedRecursion = (checked, children, isPermission = false) => {
  children.forEach(item => {
    if (item.children) {
      checkedRecursion(checked, item.children, isPermission);
    } else {
      if (isPermission) {
        item.permissions.forEach(i => i.isChecked = checked)
      } else {
        item.isChecked = checked;
      }
    }
  });
}
//保存
const save = async () => {
  loading.value = true
  try {
    await formRef.value.validate();
  } catch {
    loading.value = false
    return;
  }
  var checkedMenuPermissions = menuPermissionData.value.filter(i => i.isChecked);
  const saveData = formData.value;
  saveData.menuPermissions = checkedMenuPermissions.map(item => {
    return {
      menuId: item.id,
      permissionCodes: item.permissions.filter(i => i.isChecked).map(i => i.code)
    }
  })
  const res = await roleApi.save(saveData);
  loading.value = false
  if (res.code != 0) {
    return;
  }
  ElMessage.success("保存成功");
  formData.value.id = res.data;
  saved.value = true;
}
defineExpose({
  openCreate,
  openEditById
})
</script>
<style lang="scss">
._checkbox {
  margin-right: 10px;

  .el-checkbox__label {
    padding-left: 6px;
    font-size: 12px;
  }
}
</style>